import { configMap, createNamedStore } from "../../config/index.js"
import { arrayToValueOfConfig, closeUnwantedPages, smartParseNumber } from "../../utils/index.js"
import { getMaterial, handlePostException } from "../../api/webApi/index.js"
// 创建本地缓存存储实例
export const addFbGroupCountObjStore = createNamedStore("fb_join_group_count")
/**
 * 检测是否应该执行添加社群任务
 */
export async function shouldSkipJoinGroup(accountId, addGroupObj) {
  const addGroupDayCountKey = `facebook_add_group_day_count_${accountId}`
  const addGroupLimitCountKey = `facebook_add_group_limit_count_${accountId}`

  const today = new Date().toISOString().slice(0, 10) // 例如 "2025-04-28"

  // 获取本地存储的每日添加群组记录（对象形式）
  const addGroupDayCountMap = addFbGroupCountObjStore.get(addGroupDayCountKey) || {}
  const addGroupLimitCount = addFbGroupCountObjStore.get(addGroupLimitCountKey) || 0

  const todayAddCount = addGroupDayCountMap[today] || 0

  // 计算当天剩余可添加群组数
  let addGroupLeftCount = addGroupObj.addGroupDayCount - todayAddCount
  console.log("当天剩余可添加群组数:", addGroupLeftCount)
  if (addGroupLeftCount <= 0) {
    console.log("当天剩余可添加群组数小于等于0，不执行任务")
    return true
  }

  // 计算总剩余可添加群组数
  let addGroupLeftLimitCount = addGroupObj.addGroupLimitCount - addGroupLimitCount
  console.log("账号总共剩余可添加群组数:", addGroupLeftLimitCount)
  if (addGroupLeftLimitCount <= 0) {
    console.log("账号已添加群组数已达上限，不执行任务")
    return true
  }

  return false
}

/**
 * 更新每日添加群组记录和总数
 */
export async function updateAddGroupCount(accountId) {
  console.log("更新本地缓存")
  const addGroupDayCountKey = `facebook_add_group_day_count_${accountId}`
  const addGroupLimitCountKey = `facebook_add_group_limit_count_${accountId}`

  const today = new Date().toISOString().slice(0, 10) // 例如 "2025-04-28"

  // 先取出当前数据
  const addGroupDayCountMap = addFbGroupCountObjStore.get(addGroupDayCountKey) || {}
  const addGroupLimitCount = addFbGroupCountObjStore.get(addGroupLimitCountKey) || 0

  // 更新当天记录
  addGroupDayCountMap[today] = (addGroupDayCountMap[today] || 0) + 1

  // 更新总数
  const newAddGroupLimitCount = addGroupLimitCount + 1

  // 保存回去
  addFbGroupCountObjStore.set(addGroupDayCountKey, addGroupDayCountMap)
  addFbGroupCountObjStore.set(addGroupLimitCountKey, newAddGroupLimitCount)
}

export const fb_join_group_main = async (task, browser, index, taskId, publishPostParams) => {
  console.log("fb_join_group_main")
  // 获取任务
  const composedTask = task.composedTask
  // 获取任务配置
  const config = composedTask.config || []
  // 读取配置--每日添加群组个数
  const addGroupDayCount = arrayToValueOfConfig(config, "add_group_day_count")
  // 读取配置--账号添加群组总数
  const addGroupLimitCount = arrayToValueOfConfig(config, "add_group_limit_count")
  // 读取配置--群组人数
  const groupPersonCount = arrayToValueOfConfig(config, "group_person_count")
  const addGroupObj = {
    addGroupDayCount,
    addGroupLimitCount,
  }
  // 读取配置--搜索关键字
  const searchKeys = arrayToValueOfConfig(config, "keywords")
  // 检查当天是否满足间隔条件
  const accountId = task.platformAccount
  // 记录上次获取的已加小组总数
  const addGroupMaxCount = `facebook_add_total_count_${accountId}`
  // 直接先判断任务是否需要执行
  const shouldSkip = await shouldSkipJoinGroup(accountId, addGroupObj)
  if (shouldSkip) {
    console.log("当前任务已不满足执行条件，跳过")
    return
  }
  //  执行加入社群任务
  console.log("开始执行加入社群任务")
  const context = browser.defaultBrowserContext()
  // 设置要允许的网站（注意：必须是 HTTPS）
  const targetUrl = "https://www.facebook.com"

  // 授予所有权限
  await context.overridePermissions(targetUrl, [
    "geolocation",
    "notifications",
    "midi",
    "camera",
    "microphone",
    "background-sync",
    "ambient-light-sensor",
    "accelerometer",
    "gyroscope",
    "magnetometer",
    "clipboard-read",
    "clipboard-write",
    "payment-handler",
  ])
  // 获取页面实例
  let page = null
  try {
    // 等待10秒
    await new Promise((resolve) => setTimeout(resolve, 10000))
    // 关闭非目标页面
    await closeUnwantedPages(browser, ["www.facebook.com", "start.adspower.net"])
    // 创建新页面
    page = await browser.newPage()
    // 设置页面视口
    await page.setViewport({ width: 1920, height: 1080 })
    // 访问FaceBook首页
    console.log("正在访问FaceBook首页...")
    await page.goto(targetUrl, { waitUntil: "networkidle2", timeout: 60000 })
    // 等待页面加载完成
    await new Promise((resolve) => setTimeout(resolve, 3000))
    // 先点击社团去看已经加入了多少个社团
    // 获取小组按钮
    const groupBtnSelector = ".x1iyjqo2 > div:nth-child(1) > ul > li div.x1sxyh0"
    // 等待左侧tab列表按钮出现
    await page.waitForSelector(groupBtnSelector, { timeout: 1000 * 10 })
    // 获取按钮列表。要可见的
    const groupBtns = await page.$$(groupBtnSelector)
    for (let index = 0; index < groupBtns.length; index++) {
      const groupBtn = groupBtns[index]
      // 可见的才点击
      if (await groupBtn.boundingBox()) {
        // 在判断是不是小组。
        const groupTitle = await groupBtn.evaluate((node) => node.textContent.trim())
        if (/小组|Groups|社團/.test(groupTitle)) {
          // 是小组。直接点击
          await groupBtn.click()
          console.log("点击小组按钮完成！！！")
        }
      }
    }
    await new Promise((resolve) => setTimeout(() => resolve(), 1000 * 3))
    // 点击完毕。等待查看全部控件出现
    const myGroupListSelector = ".x1e56ztr > div > div:nth-child(3) > .x1i10hfl > .x6s0dn4"
    await page.waitForSelector(myGroupListSelector, { timeout: 1000 * 10 })
    const myGroupList = await page.$$(myGroupListSelector)
    for (let index = 0; index < myGroupList.length; index++) {
      const myGroup = myGroupList[index]
      // 获取myGroup的文案
      const myGroupText = await myGroup.evaluate((node) => node.textContent.trim())
      const box = await myGroup.boundingBox()
      if (box) {
        console.log("myGroupText=====>", myGroupText)
        console.log("box=======>", box)
        // 计算点击位置（元素中心）
        const x = box.x + box.width / 2
        const y = box.y + box.height / 2
        // 点击小组按钮
        myGroup && (await page.mouse.click(x, y, { delay: 100 }))
        console.log("点击小组完成！！！")
      }
    }
    await new Promise((resolve) => setTimeout(resolve, 1000 * 2))
    // 等待小组数量出现
    const groupCount = ".html-div:nth-child(1) .html-h2:nth-child(1) .x1lliihq:nth-child(1)"
    await page.waitForSelector(groupCount, { timeout: 1000 * 10 })
    const groupCountElements = (await page.$$(groupCount)) || []
    console.log("groupCountElements===>", groupCountElements)
    // 遍历文本为：你加入的所有社團、All groups you've joined、你加入的所有小组
    // 获取文案
    const groupCountText = await page.evaluate((el) => el.textContent.trim(), groupCountElements[groupCountElements.length - 1])
    console.log("groupCountText====>", groupCountText)
    // 提取文案里面的连续数字
    const groupCountNum = groupCountText?.match(/\d+/g)?.join("")
    console.log("groupCountNum====>", groupCountNum)
    await new Promise((resolve) => setTimeout(resolve, 1000 * 2))
    // 存一份到本地
    groupCountNum && !isNaN(parseInt(groupCountNum)) && addFbGroupCountObjStore.set(addGroupMaxCount, groupCountNum)
    // 如果已加的社群数量大于配置数量不执行
    if (groupCountNum && parseInt(groupCountNum) >= addGroupLimitCount) {
      console.log("已加的社群数量大于配置数量，不执行任务")
      return
    }
    // 点击搜索按钮
    // 查找并点击主页搜索框
    const inputSelector = "input.x2s2ed0"
    // 等待搜索框出现
    await page.waitForSelector(inputSelector, { timeout: 10 * 1000 })
    // 获取搜索框
    const inputElement = await page.$(inputSelector)
    // 点击输入框
    await inputElement.click()
    // 随机挑选一个关键词
    const randomSearchKey = searchKeys[getRandomArbitrary(0, searchKeys.length - 1)]
    // 把关键词输入到输入框中
    await inputElement.type(randomSearchKey, { delay: 50 })
    // 按下回车键
    await page.keyboard.press("Enter")
    // 等待新页面的加载
    await new Promise((resolve) => setTimeout(resolve, 1000 * 10))
    console.log("获取小组按钮")
    // 获取小组按钮
    const groupButtonSelector = "div:nth-child(8) > div > .x1i10hfl > .x6s0dn4"
    // 等待小组按钮出现
    await page.waitForSelector(groupButtonSelector, { timeout: 6 * 1000 })
    // 获取小组按钮
    const groupButtons = await page.$$(groupButtonSelector)
    // 遍历小组按钮
    for (let index = 0; index < groupButtons.length; index++) {
      const groupButton = groupButtons[index]
      // 获取可见的按钮
      const box = await groupButton.boundingBox()
      console.log("boundingBox:", box)
      console.log("groupButton===>", groupButton)
      if (box) {
        // 计算点击位置（元素中心）
        const x = box.x + box.width / 2
        const y = box.y + box.height / 2
        // 点击小组按钮
        groupButton && (await page.mouse.click(x, y, { delay: 100 }))
      }
    }
    await page.waitForSelector(groupButtonSelector, { timeout: 5 * 1000 })
    // 等待页面的列表组件出现
    const groupListSelector = "div.x1xwk8fm > div"
    await page.waitForSelector(groupListSelector, { timeout: 6 * 1000 })
    // 获取列表
    let groupList = await page.$$(groupListSelector)
    console.log("groupList=====>1", groupList)
    // 过滤出可见的列表
    let visibleGroupList = groupList.filter(async (group) => {
      return await group.boundingBox()
    })
    console.log("visibleGroupList====>", visibleGroupList)
    // 已经处理过的小组。不在处理
    const handledGroupNames = []
    // 列表触底元素选择器
    const bottomSelector = "span.x2b8uid"
    let isFinished = false
    while (!isFinished) {
      // 是否已完成
      // 遍历列表
      for (let index = 0; index < visibleGroupList.length; index++) {
        const groupItem = visibleGroupList[index]
        // 加入按钮--分为访问和加入
        const joinButtonSelector = "div.x1xwk8fm > div div.xi112ho"
        const joinButtonElement = await groupItem.$(joinButtonSelector)
        const joinButtonText = joinButtonElement ? await page.evaluate((el) => el.textContent.trim(), joinButtonElement) : ""
        console.log("joinButtonText===>", joinButtonText)
        // 获取小组名称
        const groupNameSelector = "div.x1xwk8fm > div a.xt0psk2"
        const groupNameElement = await groupItem.$(groupNameSelector)
        const groupName = groupNameElement ? await page.evaluate((el) => el.textContent.trim(), groupNameElement) : ""
        // 兼容只有四join、加入文案、没有处理过的。才需要处理
        if (/Join|加入/.test(joinButtonText) && !handledGroupNames.includes(groupName)) {
          // 需要处理
          console.log("需要处理")
        } else {
          console.log("不需要处理")
          continue
        }
        console.log("groupName====>", groupName)
        handledGroupNames.push(groupName)
        console.log("handledGroupNames====>当前已经处理过的社群", handledGroupNames)
        // 获取小组头像
        const groupAvatarSelector = "div.x1xwk8fm > div image"
        // 获取小组成员数量
        const groupMemberCountSelector = "div.x1xwk8fm > div .xo1l8bm > .x1lliihq"
        const groupMemberCountElement = await groupItem.$(groupMemberCountSelector)
        const groupMemberCountText = groupMemberCountElement ? await page.evaluate((el) => el.textContent.trim(), groupMemberCountElement) : ""
        console.log("groupMemberCountText====>", groupMemberCountText)
        // 只要公开的
        if (/公开|Public|公開/.test(groupMemberCountText)) {
          console.log("公开的小组才需要处理")
        } else {
          continue
        }
        // 把文本转换为数字
        const groupMemberCount = smartParseNumber(groupMemberCountText)
        console.log("groupMemberCount====>", groupMemberCount)
        console.log("groupItem=====>", groupItem)
        if (groupMemberCount >= groupPersonCount) {
          // 满足条件的点击加入。
          joinButtonElement && (await joinButtonElement.click())
          await new Promise((resolve) => setTimeout(resolve, 1000 * 3))
          // 等待6秒看看是否成功加入
          const singleElementSelector = 'div[role="dialog"]'
          try {
            const singleElement = await page.waitForSelector(singleElementSelector, { timeout: 6 * 1000 })
            if (singleElement && (await singleElement.boundingBox())) {
              // 表示没有成功。点击X下一个
              const closeButtonSelector = ".x92rtbv > .x1i10hfl"
              const closeButton = await singleElement.$(closeButtonSelector)
              closeButton && (await closeButton.click())
              console.log("加入失败，点击关闭按钮")
              continue
            }
          } catch (error) {
            console.log("加入成功")
          }
          console.log("加入成功")
          // 添加成功。配置本次缓存
          updateAddGroupCount(accountId)
          // 判断有没有加入完。要不要return
          const shouldSkip = await shouldSkipJoinGroup(accountId, addGroupObj)
          if (shouldSkip) {
            console.log("当前任务已不满足执行条件，跳过")
            isFinished = true
            return
          }
        } else {
          console.log(`群聊人数${groupMemberCount}小于配置人数${groupPersonCount}，不加入`)
        }
      }
      // 获取触底元素
      await new Promise((resolve) => setTimeout(resolve, 1000 * 10))
      // 获取触底元素
      const bottomElement = await page.$(bottomSelector)
      if (bottomElement && (await bottomElement.boundingBox())) {
        console.log("触底元素存在，已加载完全部的列表元素")
        break
      }
      // 如果没有触底就滚动
      const isReachedBottom = await scrollToBottom(1000, page)
      console.log("是否到底部:", isReachedBottom)
      // 重新获取小组列表
      groupList = await page.$$(groupListSelector)
      console.log("groupList=====>2", groupList)
      visibleGroupList = groupList.filter(async (group) => {
        return await group.boundingBox()
      })
    }
  } catch (error) {
    console.log("加入社群任务执行失败", error)
  }
}
/**
 * 生成指定范围内的随机整数（包括最小值和最大值）
 * @param {number} min - 最小值（包括）
 * @param {number} max - 最大值（包括）
 * @returns {number} 生成的随机整数
 */
export function getRandomArbitrary(min, max) {
  // 将 min 和 max 转换为数字并检查是否有效
  const minNum = Number(min)
  const maxNum = Number(max)

  // 检查是否为有效数字
  if (isNaN(minNum) || isNaN(maxNum)) {
    console.log("min 或 max 不是有效的数字")
    return 0
  }

  // 确保 min <= max
  if (minNum > maxNum) {
    console.log("min 不能大于 max")
    return 0
  }

  // 生成随机整数
  return Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum
}
async function scrollToBottom(step = 100, page) {
  const scrollResult = await page.evaluate(async (step) => {
    const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms))

    // 获取滚动前的位置
    const beforeScrollY = window.scrollY
    console.log("滚动前位置:", beforeScrollY)

    // 计算合理的滚动步长
    const scrollStep = step + Math.random() * step * 0.5 // 每次滚动 100-150px，减小随机性
    const scrollDelay = 50 + Math.random() * 100 // 每次滚动间隔 50-150ms，更流畅

    // 使用相对滚动，从当前位置滚动一定距离，而不是绝对位置
    window.scrollBy({
      top: scrollStep,
      behavior: "smooth", // 使用平滑滚动
    })

    await delay(scrollDelay)

    // 模拟偶尔停顿，但减少概率
    if (Math.random() < 0.1) {
      const pauseTime = 500 + Math.random() * 1000 // 0.5-1.5秒的停顿，缩短停顿时间
      await delay(pauseTime)
    }

    // 获取滚动后的位置，并确认滚动是否有效
    const afterScrollY = window.scrollY
    console.log("滚动后位置:", afterScrollY)

    // 计算滚动是否有效（是否真的向下滚动了）
    const scrolledEffectively = afterScrollY > beforeScrollY

    // 判断是否到底部
    const reachedBottom = document.documentElement.scrollTop + window.innerHeight >= document.documentElement.scrollHeight - 10 // 添加10px的容差

    return {
      reachedBottom,
      scrolledEffectively,
      beforePosition: beforeScrollY,
      afterPosition: afterScrollY,
    }
  }, step)

  // 记录滚动结果
  console.log(`滚动结果: 到达底部=${scrollResult.reachedBottom}, 有效滚动=${scrollResult.scrolledEffectively}, 位置变化=${scrollResult.beforePosition} -> ${scrollResult.afterPosition}`)

  // 如果滚动无效，可以认为已经到底
  if (!scrollResult.scrolledEffectively) {
    console.log("滚动无效，可能已经到底或遇到阻碍")
  }

  return scrollResult.reachedBottom
}

